package com.cencat.common.utils;

import com.cencat.common.constants.CommonConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;

/**
 * 多租户工具类
 * 提供租户信息获取和设置功能
 * 
 * @author cencat
 * @since 2024-01-01
 */
public class TenantUtils {

    private static final Logger log = LoggerFactory.getLogger(TenantUtils.class);

    /**
     * 私有构造函数，防止实例化
     */
    private TenantUtils() {
    }

    /**
     * 租户ID的ThreadLocal
     */
    private static final ThreadLocal<Long> TENANT_CONTEXT = new ThreadLocal<>();
    
    /**
     * 超级管理员标识的ThreadLocal
     */
    private static final ThreadLocal<Boolean> SUPER_ADMIN_CONTEXT = new ThreadLocal<>();
    
    /**
     * 忽略租户过滤标识的ThreadLocal
     */
    private static final ThreadLocal<Boolean> IGNORE_TENANT_CONTEXT = new ThreadLocal<>();

    /**
     * 获取当前租户ID
     * 
     * @return 租户ID
     */
    public static Long getCurrentTenantId() {
        // 优先从线程变量获取
        Long tenantId = TENANT_CONTEXT.get();
        if (tenantId != null) {
            return tenantId;
        }

        // 从HTTP请求头获取
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String tenantIdStr = request.getHeader(CommonConstants.TENANT_ID_HEADER);
                if (CencatStringUtils.isNotBlank(tenantIdStr)) {
                    tenantId = Long.parseLong(tenantIdStr);
                    setCurrentTenantId(tenantId);
                    return tenantId;
                }
            }
        } catch (Exception e) {
            log.warn("获取租户ID失败: {}", e.getMessage());
        }

        // 返回默认租户ID
        return CommonConstants.Business.DEFAULT_TENANT_ID;
    }

    /**
     * 设置当前租户ID
     * 
     * @param tenantId 租户ID
     */
    public static void setCurrentTenantId(Long tenantId) {
        if (tenantId != null && tenantId > 0) {
            TENANT_CONTEXT.set(tenantId);
            log.debug("设置租户ID: {}", tenantId);
        }
    }

    /**
     * 清除当前租户ID
     */
    public static void clearCurrentTenantId() {
        TENANT_CONTEXT.remove();
        log.debug("清除租户ID");
    }
    
    /**
     * 检查是否为超级管理员
     * 
     * @return 是否为超级管理员
     */
    public static boolean isSuperAdmin() {
        Boolean superAdmin = SUPER_ADMIN_CONTEXT.get();
        return superAdmin != null && superAdmin;
    }
    
    /**
     * 设置超级管理员标识
     * 
     * @param superAdmin 是否为超级管理员
     */
    public static void setSuperAdmin(boolean superAdmin) {
        if (superAdmin) {
            SUPER_ADMIN_CONTEXT.set(true);
            log.debug("设置超级管理员标识: true");
        } else {
            SUPER_ADMIN_CONTEXT.remove();
            log.debug("清除超级管理员标识");
        }
    }
    
    /**
     * 检查是否忽略租户过滤
     * 
     * @return 是否忽略租户过滤
     */
    public static boolean isIgnoreTenant() {
        Boolean ignoreTenant = IGNORE_TENANT_CONTEXT.get();
        return ignoreTenant != null && ignoreTenant;
    }
    
    /**
     * 设置忽略租户过滤标识
     * 
     * @param ignoreTenant 是否忽略租户过滤
     */
    public static void setIgnoreTenant(boolean ignoreTenant) {
        if (ignoreTenant) {
            IGNORE_TENANT_CONTEXT.set(true);
            log.debug("设置忽略租户过滤: true");
        } else {
            IGNORE_TENANT_CONTEXT.remove();
            log.debug("清除忽略租户过滤标识");
        }
    }
    
    /**
     * 清除所有上下文信息
     */
    public static void clearAllContext() {
        TENANT_CONTEXT.remove();
        SUPER_ADMIN_CONTEXT.remove();
        IGNORE_TENANT_CONTEXT.remove();
        log.debug("清除所有租户上下文信息");
    }

    /**
     * 检查是否为默认租户
     * 
     * @return 是否为默认租户
     */
    public static boolean isDefaultTenant() {
        Long tenantId = getCurrentTenantId();
        return CommonConstants.Business.DEFAULT_TENANT_ID.equals(tenantId);
    }

    /**
     * 检查是否为有效租户ID
     * 
     * @param tenantId 租户ID
     * @return 是否有效
     */
    public static boolean isValidTenantId(Long tenantId) {
        return tenantId != null && tenantId > 0;
    }

    /**
     * 验证租户是否有效（字符串类型租户ID）
     * 
     * @param tenantId 租户ID字符串
     * @return 是否有效
     */
    public static boolean isValidTenant(String tenantId) {
        if (CencatStringUtils.isBlank(tenantId)) {
            return false;
        }
        
        try {
            Long tenantIdLong = Long.parseLong(tenantId);
            return isValidTenantId(tenantIdLong);
        } catch (NumberFormatException e) {
            log.warn("租户ID格式错误: {}", tenantId);
            return false;
        }
    }

    /**
     * 获取租户数据库表前缀
     * 
     * @return 表前缀
     */
    public static String getTenantTablePrefix() {
        Long tenantId = getCurrentTenantId();
        if (isDefaultTenant()) {
            return "";
        }
        return "t" + tenantId + "_";
    }

    /**
     * 获取租户缓存键前缀
     * 
     * @param baseKey 基础键
     * @return 带租户前缀的缓存键
     */
    public static String getTenantCacheKey(String baseKey) {
        if (CencatStringUtils.isBlank(baseKey)) {
            return baseKey;
        }
        
        Long tenantId = getCurrentTenantId();
        return "tenant:" + tenantId + ":" + baseKey;
    }

    /**
     * 执行带租户上下文的操作
     * 
     * @param tenantId 租户ID
     * @param runnable 执行的操作
     */
    public static void executeWithTenant(Long tenantId, Runnable runnable) {
        Long originalTenantId = TENANT_CONTEXT.get();
        try {
            setCurrentTenantId(tenantId);
            runnable.run();
        } finally {
            if (originalTenantId != null) {
                setCurrentTenantId(originalTenantId);
            } else {
                clearCurrentTenantId();
            }
        }
    }

    /**
     * 执行带租户上下文的操作（有返回值）
     * 
     * @param tenantId 租户ID
     * @param supplier 执行的操作
     * @param <T> 返回值类型
     * @return 操作结果
     */
    public static <T> T executeWithTenant(Long tenantId, java.util.function.Supplier<T> supplier) {
        Long originalTenantId = TENANT_CONTEXT.get();
        try {
            setCurrentTenantId(tenantId);
            return supplier.get();
        } finally {
            if (originalTenantId != null) {
                setCurrentTenantId(originalTenantId);
            } else {
                clearCurrentTenantId();
            }
        }
    }

    /**
     * 生成租户相关的唯一标识
     * 
     * @param prefix 前缀
     * @return 唯一标识
     */
    public static String generateTenantUniqueId(String prefix) {
        Long tenantId = getCurrentTenantId();
        String uuid = java.util.UUID.randomUUID().toString().replace("-", "");
        
        if (CencatStringUtils.isNotBlank(prefix)) {
            return prefix + "_" + tenantId + "_" + uuid;
        }
        
        return tenantId + "_" + uuid;
    }

    /**
     * 检查租户权限
     * 
     * @param targetTenantId 目标租户ID
     * @return 是否有权限
     */
    public static boolean hasPermission(Long targetTenantId) {
        if (!isValidTenantId(targetTenantId)) {
            return false;
        }
        
        Long currentTenantId = getCurrentTenantId();
        
        // 默认租户可以访问所有租户数据（超级管理员）
        if (isDefaultTenant()) {
            return true;
        }
        
        // 普通租户只能访问自己的数据
        return currentTenantId.equals(targetTenantId);
    }

    /**
     * 租户上下文信息
     */
    public static class TenantContext {
        private final Long tenantId;
        private final String tablePrefix;
        private final boolean isDefault;

        public TenantContext(Long tenantId) {
            this.tenantId = tenantId;
            this.tablePrefix = getTenantTablePrefix();
            this.isDefault = isDefaultTenant();
        }

        public Long getTenantId() {
            return tenantId;
        }

        public String getTablePrefix() {
            return tablePrefix;
        }

        public boolean isDefault() {
            return isDefault;
        }

        @Override
        public String toString() {
            return "TenantContext{" +
                    "tenantId=" + tenantId +
                    ", tablePrefix='" + tablePrefix + '\'' +
                    ", isDefault=" + isDefault +
                    '}';
        }
    }

    /**
     * 获取当前租户上下文信息
     * 
     * @return 租户上下文
     */
    public static TenantContext getCurrentTenantContext() {
        return new TenantContext(getCurrentTenantId());
    }
}